/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.voltor.core.nodes;


import java.awt.Image;
import java.awt.event.ActionEvent;
import java.beans.IntrospectionException;
import java.beans.PropertyChangeEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import org.openide.ErrorManager;
import org.openide.nodes.*;
import org.openide.util.Exceptions;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups;
import org.voltor.core.VoltorEntity;
import org.voltor.core.DynamicProperty;
import org.voltor.core.ui.VoltorEntityEditorWindow;

/**
 *
 * @author alext
 */
public class VoltorEntityNodeCreationFactory extends ChildFactory<VoltorEntity> {

    private List<VoltorEntity> resultList;

    public VoltorEntityNodeCreationFactory() {
        this.resultList = new ArrayList<VoltorEntity>();
    }

    public VoltorEntityNodeCreationFactory(VoltorEntity device) {
        this();
        List<VoltorEntity> t = new ArrayList<VoltorEntity>();
        t.add(device);
    }

    public VoltorEntityNodeCreationFactory(List<VoltorEntity> resultList) {
        this.resultList = resultList;
    }

    @Override
    protected boolean createKeys(List<VoltorEntity> list) {
        for (VoltorEntity device : resultList) {
            list.add(device);
        }
        return true;
    }

    @Override
    protected Node createNodeForKey(VoltorEntity key) {
        try {
            return new VoltorEntityNode(key);
        } catch (IntrospectionException ex) {
            ex.printStackTrace();
            Exceptions.printStackTrace(ex);
        }
        return null;
    }

    public class VoltorEntityNode extends AbstractNode implements java.beans.PropertyChangeListener {

        private VoltorEntity entity = null;

        public VoltorEntityNode(VoltorEntity obj) throws IntrospectionException {
            super(Children.create(new VoltorEntityNodeCreationFactory(obj), false), Lookups.singleton(obj));
            setDisplayName(obj.getName());
            obj.addPropertyChangeListener(WeakListeners.propertyChange(this, obj));
            this.entity = obj;
        }

        @Override
        protected Sheet createSheet() {
            Sheet sheet = Sheet.createDefault();
            Sheet.Set basicProperties = Sheet.createPropertiesSet();
            Sheet.Set extendedProperties = Sheet.createPropertiesSet();

            basicProperties.setDisplayName("General Info");
            basicProperties.setName("General");
            extendedProperties.setValue("tabName", "General");

            extendedProperties.setDisplayName("Extended Info");
            extendedProperties.setName("Extended");
            extendedProperties.setValue("tabName", "Extended Info");

            VoltorEntity obj = getLookup().lookup(VoltorEntity.class);
            try {
                Node.Property<String> typeProp = new PropertySupport.Reflection(obj, String.class, "type");
                Node.Property<String> nameProp = new PropertySupport.Reflection(obj, String.class, "name");
                Node.Property<String> descriptionProp = new PropertySupport.Reflection(obj, String.class, "description");

                typeProp.setName("Type");

                nameProp.setName("Name");
                descriptionProp.setName("Description");

                basicProperties.put(typeProp);
                basicProperties.put(nameProp);
                basicProperties.put(descriptionProp);

                for (DynamicProperty extendedProperty : obj.getExtendedProperties()) {
                    extendedProperties.put(extendedProperty);
                }

            } catch (NoSuchMethodException ex) {
                ErrorManager.getDefault();
            }

            sheet.put(basicProperties);
            sheet.put(extendedProperties);
            return sheet;

        }

        @Override
        public String getHtmlDisplayName() {
            VoltorEntity obj = getLookup().lookup(VoltorEntity.class);
            if (obj != null) {
                return "<font color='!textText'> " + obj.getName() + "</font>"
                        + "<font color='!controlShadow'><i>  [Type:" + obj.getType() + "]</i></font>";
            } else {
                return null;
            }
        }

        @Override
        public Action[] getActions(boolean context) {
            return new Action[]{new AddEntityAction(this), new EditEntityAction(this), new RemoveEntityAction(this)};
        }

        @Override
        public void propertyChange(PropertyChangeEvent pce) {
            this.fireDisplayNameChange(null, getDisplayName());
        }

        @Override
        public Image getIcon(int type) {
           return ImageUtilities.loadImage(entity.getClosedEntityImage());
        }

        @Override
        public Image getOpenedIcon(int type) {
            return ImageUtilities.loadImage(entity.getClosedEntityImage());
        }

        
        /**
         * @return the entity
         */
        public VoltorEntity getEntity() {
            return entity;
        }
    }

    private class AddEntityAction extends AbstractAction {

        private Lookup lookup = null;
        private VoltorEntityNode node = null;

        public AddEntityAction(VoltorEntityNode node) {
            putValue(NAME, "Add");
            this.lookup = node.getLookup();
            this.node = node;
        }

        @Override
        public void actionPerformed(ActionEvent ae) {
            VoltorEntity entity = lookup.lookup(VoltorEntity.class);
            VoltorEntity newEntity = new VoltorEntity();

            VoltorEntityEditorWindow window = new VoltorEntityEditorWindow(entity, newEntity);
            window.setVisible(true);

            try {
                VoltorEntityNode newNode = new VoltorEntityNode(newEntity);
                if (window.isSibling()) {
                    node.getParentNode().getChildren().add(new Node[]{newNode});
                } else {
                    node.getChildren().add(new Node[]{newNode});
                }
            } catch (IntrospectionException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    }

    private class EditEntityAction extends AbstractAction {
       
        private VoltorEntityNode node = null;

        public EditEntityAction(VoltorEntityNode node) {
            putValue(NAME, "Edit");            
            this.node = node;
        }

        @Override
        public void actionPerformed(ActionEvent ae) {                       
            VoltorEntity entity = ((VoltorEntityNode) node).getEntity();
            VoltorEntityEditorWindow window = new VoltorEntityEditorWindow(entity, entity);
            window.setVisible(true);
        }
    }

    private class RemoveEntityAction extends AbstractAction {

        private VoltorEntityNode node = null;

        public RemoveEntityAction(VoltorEntityNode node) {
            putValue(NAME, "Remove");            
            this.node = node;
        }

        @Override
        public void actionPerformed(ActionEvent ae) {
            node.getParentNode().getChildren().remove(new Node[]{node});
        }
    }
}
